package com.flyox.game.fivetiger.control;

import javax.swing.JOptionPane;

import com.flyox.game.fivetiger.bean.CONSTS;
import com.flyox.game.fivetiger.bean.MsgPackage;
import com.flyox.game.fivetiger.model.Document;
import com.flyox.game.fivetiger.server.BroadCastServer;
import com.flyox.game.fivetiger.server.DataTrafficCenter;
import com.flyox.game.fivetiger.tools.UtilBean;
import com.flyox.game.fivetiger.view.ChessOptionsJDialog;
import com.flyox.game.fivetiger.view.FivetigerJFrame;

/**
 * 画面事件的处理中心
 * 
 * @author sunwei
 * 
 */
public class FivetigerControl {

	private FivetigerJFrame view;
	private Document doc;
	private DataTrafficCenter dataTraffic;
	private BroadCastServer broadCastServer;

	private Thread dataTrafficThread;
	private Thread broadCastThread;

	public UtilBean utilBean;

	public FivetigerControl() {
		utilBean = new UtilBean();
	}

	/**
	 * 创建服务端socket
	 */
	public void createDataTrafficServer() {
		dataTraffic = DataTrafficCenter.getServerInstance(this);
		dataTrafficThread = new Thread(dataTraffic);
		dataTrafficThread.start();

		doc.reInit();
		doc.setName(CONSTS.SYS_SERVER_NAME);
		doc.setCurrentPlayer(CONSTS.SYS_CLIENT_NAME);
		doc.setCurrentState(CONSTS.CMD_WAIT);
		// SwingUtilities.invokeLater(con);
		// SwingUtilities.invokeAndWait(con);//直到getValue可运行的run方法返回后才返回
	}

	/**
	 * 链接服务端socket 并开始 游戏
	 * 
	 * @param ip
	 */
	public void connectDataTrafficServer(String ip) {
		if (ip == null) {
			return;
		}
		dataTraffic = DataTrafficCenter.getClientInstance(this, ip);
		new Thread(dataTraffic).start();
		doc.setName(CONSTS.SYS_CLIENT_NAME);
		doc.setStateMsg("链接成功！");
		try {
			Thread.sleep(500);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		MsgPackage msgPackage = new MsgPackage();
		msgPackage.setCmd(CONSTS.CMD_HELLO);
		msgPackage.setCmdPlayer(CONSTS.SYS_CLIENT_NAME);
		boolean res = sendMsg(msgPackage);
		if (!res) {
			doc.setStateMsg("链接失败！");
		} else {
			// processBegin(CONSTS.SYS_SERVER_NAME);
			view.changeToConnectStat();
		}
	}

	/**
	 * 创建广播服务器
	 * 
	 * @param isServer
	 */
	public void createBoardServer() {
		broadCastServer = BroadCastServer.getServerInstance(this);
		broadCastThread = new Thread(broadCastServer);
		broadCastThread.start();
	}

	/**
	 * 查询游戏服务器
	 */
	public void queryDataTrafficServers() {
		broadCastServer = BroadCastServer.getClientInstance(this);
		Thread ct = new Thread(broadCastServer);
		ct.start();
		broadCastServer.searchServer();
	}

	/**
	 * 结束链接
	 */
	public void close() {
		doc.reInit();
		view.conClosed();
		dataTraffic.close();
		broadCastServer.close();
	}

	// CMD_DOGFALL=10;// 平局
	// CMD_REQUEST_DOGFALL=11;//求和
	// CMD_GIVE_UP=11;//投降
	public void sendCMD(int cmd) {
		MsgPackage msgPackage = new MsgPackage();
		msgPackage.setCmd(cmd);
		dataTraffic.sendMsg(msgPackage);
	}

	public boolean sendMsg(MsgPackage msgPackage) {
		if (dataTraffic == null) {
			return false;
		} else {
			return dataTraffic.sendMsg(msgPackage);
		}
	}

	/**
	 * 处理接收到的下棋操作
	 * 
	 * @param msg
	 */
	private void processReciveAdd(MsgPackage msg) {
		doc.pushStept(msg);

		doc.addOtherSidePlayerChess(msg.getFirstPos());
		doc.setCurrentPlayer(msg.getCurrentPlayer());
		doc.setCurrentState(msg.getCurrentState());
		doc.setCanRemoveChessCount(msg.getCanRemoveChessCount());

		checkCurrentState();
	}

	/**
	 * 处理接收到的压棋操作
	 * 
	 * @param msg
	 */
	private void processReciveCover(MsgPackage msg) {
		doc.pushStept(msg);

		doc.setOnCover(msg.getFirstPos());//
		doc.setCurrentPlayer(msg.getCurrentPlayer());
		doc.setCurrentState(msg.getCurrentState());
		doc.setCanRemoveChessCount(msg.getCanRemoveChessCount());

		checkCurrentState();
	}

	/**
	 * 处理接收到的走棋操作
	 * 
	 * @param msg
	 */
	private void processReciveMove(MsgPackage msg) {
		doc.pushStept(msg);

		doc.setCurrentPlayer(msg.getCurrentPlayer());
		doc.setCurrentState(msg.getCurrentState());
		doc.setCanRemoveChessCount(msg.getCanRemoveChessCount());
		doc.move(msg.getFirstPos(), msg.getSecondPos());

		checkCurrentState();
	}

	/**
	 * 处理接收到的拔棋操作
	 * 
	 * @param msg
	 */
	private void processReciveCut(MsgPackage msg) {
		doc.pushStept(msg);
		// 更新doc
		doc.cutChess(msg.getFirstPos());
		doc.setCurrentPlayer(msg.getCurrentPlayer());
		doc.setCurrentState(msg.getCurrentState());
		doc.setCanRemoveChessCount(msg.getCanRemoveChessCount());

		checkCurrentState();
	}

	public void processBegin(String currentPlayer) {
		doc.reInit();
		doc.setCurrentPlayer(currentPlayer);
		doc.setCurrentState(CONSTS.CMD_ADD);
		view.changeToBeginState();
	}

	/**
	 * 发送投降请求
	 */
	public void sendGiveUp() {
		MsgPackage msg = new MsgPackage();
		msg.setCmd(CONSTS.CMD_GIVE_UP);
		msg.setCurrentPlayer(doc.getName());
		msg.setCurrentState(CONSTS.CMD_ADD);
		sendMsg(msg);

		processBegin(doc.getName());
	}

	/**
	 * 发送平棋请求
	 */
	public void sendRequestDogfall() {
		MsgPackage msg = new MsgPackage();
		msg.setCmd(CONSTS.CMD_REQUEST_DOGFALL);
		msg.setCurrentPlayer(doc.getName());
		msg.setCurrentState(CONSTS.CMD_ADD);
		sendMsg(msg);
	}

	private void processRefuseUndo(MsgPackage msg) {
		doc.setCurrentPlayer(msg.getCurrentPlayer());
		doc.setCurrentState(msg.getCurrentState());
		view.jButtonUndo.setEnabled(true);
		JOptionPane.showMessageDialog(view, msg.getMsg());
	}

	/**
	 * 处理对方的悔棋请求
	 */
	private void processRequestUndo() {
		if (JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(view, "对方请求悔棋，是否接受？", "提示", JOptionPane.YES_NO_OPTION)) {
			MsgPackage msg = doc.peepStept();
			if (msg.getCurrentPlayer().equals(doc.getName())) {
				undo(doc.popStept());
				msg = doc.peepStept();
			} else {// 对方走棋
				while (msg.getCmdPlayer().equals(doc.getName())) {
					undo(doc.popStept());
					msg = doc.peepStept();
				}
				//
				undo(doc.popStept());// other
				msg = doc.peepStept();
			}
			//
			doc.setCurrentPlayer(doc.getOtherSideName());
			doc.setCurrentState(msg.getCurrentState());

			MsgPackage response = new MsgPackage();
			response.setCmd(CONSTS.CMD_UNDO);
			response.setCmdPlayer(doc.getCurrentPlayer());
			response.setCurrentPlayer(doc.getOtherSideName());
			response.setCurrentState(doc.getCurrentState());

			sendMsg(response);
		} else {
			MsgPackage response = new MsgPackage();
			response.setCmd(CONSTS.CMD_REFUSED_UNDO);
			response.setCmdPlayer(doc.getCurrentPlayer());
			response.setCurrentPlayer(doc.peepStept().getCurrentPlayer());
			response.setCurrentState(doc.peepStept().getCurrentState());
			response.setMsg("对方拒绝求和");
			sendMsg(response);
		}
	}

	/**
	 * 发送悔棋请求
	 */
	public void sendUndoRequest() {
		if (doc.isSteptsNull()) {
			return;
		}
		// 发送信息给对方
		MsgPackage msgPackage = new MsgPackage();
		msgPackage.setCmdPlayer(doc.getCurrentPlayer());
		msgPackage.setCmd(CONSTS.CMD_REQUEST_UNDO);
		msgPackage.setCurrentPlayer(doc.getOtherSideName());

		doc.setCurrentState(CONSTS.CMD_REQUEST_UNDO);
		doc.setCurrentPlayer(doc.getOtherSideName());

		sendMsg(msgPackage);
	}

	private void processUndo() {
		MsgPackage msg = doc.peepStept();
		if (msg.getCurrentPlayer().equals(doc.getOtherSideName())) {
			undo(doc.popStept());
			msg = doc.peepStept();
		} else {
			while (msg.getCmdPlayer().equals(doc.getOtherSideName())) {
				undo(doc.popStept());
				msg = doc.peepStept();
			}
			undo(doc.popStept());
			msg = doc.peepStept();
		}
		//
		doc.setCurrentPlayer(doc.getName());
		doc.setCurrentState(msg.getCurrentState());
		doc.setCanRemoveChessCount(msg.getCanRemoveChessCount());
		if (!utilBean.haveAnyChessCanMove(doc.getLayout(), doc.getTeamFlag())) {
			doc.setOtherSideNeedCut(true);// 标记对方也可以拔掉一个棋子
		}
		view.jButtonUndo.setEnabled(true);
	}

	// view
	private void undo(MsgPackage msg) {
		if (msg == null) {
			return;
		}
		switch (msg.getCmd()) {
		case CONSTS.CMD_ADD:
			if (msg.getFullLayout() != null) {
				doc.setLayout(msg.getFullLayout());
			}
			doc.cutChess(msg.getFirstPos());
			break;
		case CONSTS.CMD_COVER:
			if (msg.getFullLayout() != null) {
				doc.setLayout(msg.getFullLayout());
			}
			doc.unDoOnCover(msg.getFirstPos());
			break;
		case CONSTS.CMD_MOVE:
			doc.move(msg.getSecondPos(), msg.getFirstPos());
			break;
		case CONSTS.CMD_CUT:
			MsgPackage pre = doc.peepStept();
			if (pre.getCurrentPlayer().equals(CONSTS.SYS_SERVER_NAME)) {
				doc.setLayout(msg.getFirstPos(), CONSTS.CHESS_THREE);
			} else {
				doc.setLayout(msg.getFirstPos(), CONSTS.CHESS_ZERO);
			}
			break;
		default:
			break;
		}
	}

	/**
	 * 处理求和信息
	 * 
	 * @param msg
	 */
	private void processRequestDogfall(MsgPackage msg) {
		if (JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(view, "对方求和，是否接受？", "提示", JOptionPane.YES_NO_OPTION)) {
			processBegin(msg.getCurrentPlayer());
			MsgPackage response = new MsgPackage();
			response.setCmd(CONSTS.CMD_BEGIN);
			response.setCmdPlayer(doc.getCurrentPlayer());
			response.setCurrentPlayer(msg.getCurrentPlayer());
			response.setCurrentState(CONSTS.CMD_ADD);
			sendMsg(response);
		} else {
			MsgPackage response = new MsgPackage();
			response.setCmd(CONSTS.CMD_MSG);
			response.setMsg("对方拒绝求和");
			sendMsg(response);
		}
	}

	private void processShowOpt(MsgPackage msg) {
		if (doc.getChessOptions().equals(msg.getChessOptions())) {
			sendBeginCMD();
		} else {
			ChessOptionsJDialog inst = new ChessOptionsJDialog(this, msg.getChessOptions(), true);
			inst.setLocationRelativeTo(null);
			inst.setVisible(true);

			if (doc.getChessOptions().equals(msg.getChessOptions())) {
				sendBeginCMD();
			} else {
				sendShowOptCMD();
			}
		}
	}

	public void sendBeginCMD() {
		doc.reInit();
		doc.setCurrentPlayer(doc.getChessOptions().getWhoFirst());
		doc.setCurrentState(CONSTS.CMD_ADD);

		view.changeToBeginState();

		MsgPackage msgPackage = new MsgPackage();
		msgPackage.setCmd(CONSTS.CMD_BEGIN);
		msgPackage.setCmdPlayer(doc.getName());
		msgPackage.setCurrentPlayer(doc.getChessOptions().getWhoFirst());
		msgPackage.setCurrentState(CONSTS.CMD_ADD);
		sendMsg(msgPackage);
	}

	public void sendShowOptCMD() {
		doc.setCurrentPlayer(doc.getOtherSideName());
		doc.setCurrentState(CONSTS.CMD_SHOWOPT);

		MsgPackage response = new MsgPackage();
		response.setCmd(CONSTS.CMD_SHOWOPT);
		response.setCmdPlayer(doc.getName());
		response.setChessOptions(doc.getChessOptions());
		sendMsg(response);
	}

	/**
	 * 处理接收到的消息 CONSTS.CMD_HELLO
	 * 
	 * @param msg
	 */
	public void process(MsgPackage msg) {
		switch (msg.getCmd()) {
		case CONSTS.CMD_HELLO:
			sendShowOptCMD();
			break;
		case CONSTS.CMD_SHOWOPT:
			processShowOpt(msg);
			break;
		case CONSTS.CMD_BEGIN:
			processBegin(msg.getCurrentPlayer());
			// broadCastServer.close();
			break;
		case CONSTS.CMD_ADD:
			processReciveAdd(msg);
			break;
		case CONSTS.CMD_COVER:
			processReciveCover(msg);
			break;
		case CONSTS.CMD_MOVE:
			processReciveMove(msg);
			break;
		case CONSTS.CMD_CUT:
			processReciveCut(msg);
			break;
		case CONSTS.CMD_REQUEST_UNDO: // 请求悔棋
			processRequestUndo();
			break;
		case CONSTS.CMD_REFUSED_UNDO: // 拒绝悔棋
			processRefuseUndo(msg);
			break;
		case CONSTS.CMD_UNDO: // 悔棋
			processUndo();
			break;
		case CONSTS.CMD_DOGFALL:// 平局 系统判断
			JOptionPane.showMessageDialog(view, "平棋！", "恭喜", JOptionPane.INFORMATION_MESSAGE, null);
			processBegin(msg.getCurrentPlayer());
			break;
		case CONSTS.CMD_REQUEST_DOGFALL: // 求和
			processRequestDogfall(msg);
			break;
		case CONSTS.CMD_GIVE_UP: // 投降
			JOptionPane.showMessageDialog(view, "对方投降！", "恭喜", JOptionPane.INFORMATION_MESSAGE, null);
			processBegin(msg.getCurrentPlayer());
			break;
		case CONSTS.CMD_FAIL: // 失败
			JOptionPane.showMessageDialog(view, "下次再努力！", "提示", JOptionPane.INFORMATION_MESSAGE, null);
			processBegin(msg.getCurrentPlayer());
			break;
		case CONSTS.CMD_WIN: // 失败
			JOptionPane.showMessageDialog(view, "你赢了！", "恭喜", JOptionPane.INFORMATION_MESSAGE, null);
			processBegin(msg.getCurrentPlayer());
			break;
		case CONSTS.CMD_MSG:
			if (msg.getMsg().equals("对方拒绝求和")) {
				view.jButtonRequestDogfall.setEnabled(true);
			}
			JOptionPane.showMessageDialog(view, msg.getMsg());
			break;
		case CONSTS.CMD_TEST:
			break;
		default:
			break;
		}
	}

	private void checkCurrentState() {
		if (!doc.isCurrentPlayerPlay()) {
			return;
		}
		// 检查是否有棋可走
		if (doc.getCurrentState() == CONSTS.CMD_MOVE) {
			doc.removeAllCovered();
			if (doc.isOver(doc.getTeamFlag())) {
				doc.setStateMsg("你失败了");

				MsgPackage response = new MsgPackage();
				response.setCmd(CONSTS.CMD_WIN);
				response.setCurrentPlayer(doc.getName());
				response.setCurrentState(CONSTS.CMD_ADD);
				response.setCmdPlayer(doc.getCurrentPlayer());
				sendMsg(response);
				JOptionPane.showMessageDialog(view, "下次再努力！", "提示", JOptionPane.INFORMATION_MESSAGE, null);
				processBegin(doc.getName());
			} else if (!utilBean.haveAnyChessCanMove(doc.getLayout(), doc.getTeamFlag())) {
				doc.setCurrentState(CONSTS.CMD_CUT);
				doc.setCanRemoveChessCount(1);
				doc.setOtherSideNeedCut(true);// 标记对方也可以拔掉一个棋子
				// 检查是否有棋可拔
				if (!utilBean.haveAnyChessRemove(doc.getLayout(), doc.getOtherSideTeamFlag())) {
					// 平棋 发送通知
					sendCMD(CONSTS.CMD_DOGFALL);
					JOptionPane.showMessageDialog(view, "平棋！", "恭喜", JOptionPane.INFORMATION_MESSAGE, null);
					processBegin(CONSTS.SYS_SERVER_NAME);
				}
			}
		} else if (doc.getCurrentState() == CONSTS.CMD_CUT) {
			if (doc.isOver(doc.getTeamFlag())) {
				doc.setStateMsg("你失败了");

				MsgPackage response = new MsgPackage();
				response.setCmd(CONSTS.CMD_WIN);
				response.setCurrentPlayer(doc.getName());
				response.setCurrentState(CONSTS.CMD_ADD);
				response.setCmdPlayer(doc.getCurrentPlayer());
				sendMsg(response);
				JOptionPane.showMessageDialog(view, "下次再努力！", "提示", JOptionPane.INFORMATION_MESSAGE, null);
				processBegin(doc.getName());
			} else if (doc.isOver(doc.getOtherSideTeamFlag())) {
				doc.setStateMsg("你赢了");

				MsgPackage response = new MsgPackage();
				response.setCmd(CONSTS.CMD_FAIL);
				response.setCurrentPlayer(doc.getOtherSideName());
				response.setCurrentState(CONSTS.CMD_ADD);
				response.setCmdPlayer(doc.getCurrentPlayer());
				sendMsg(response);
				JOptionPane.showMessageDialog(view, "你赢了！", "恭喜", JOptionPane.INFORMATION_MESSAGE, null);
				processBegin(doc.getOtherSideName());
			} else if (!utilBean.haveAnyChessRemove(doc.getLayout(), doc.getOtherSideTeamFlag())) {
				// 平棋 发送通知
				sendCMD(CONSTS.CMD_DOGFALL);
				JOptionPane.showMessageDialog(view, "平棋！", "恭喜", JOptionPane.INFORMATION_MESSAGE, null);
				processBegin(CONSTS.SYS_SERVER_NAME);
			}
		}
	}

	public void play(MsgPackage msg) {
		if (msg == null) {
			return;
		}
		switch (msg.getCmd()) {
		case CONSTS.CMD_ADD:
			if (msg.getCmdPlayer().equals(CONSTS.SYS_SERVER_NAME)) {
				doc.addCurrenPlayerChess(msg.getFirstPos());
			} else {
				doc.addOtherSidePlayerChess(msg.getFirstPos());
			}
			doc.setCurrentPlayer(msg.getCurrentPlayer());
			doc.setCurrentState(msg.getCurrentState());
			doc.setCanRemoveChessCount(msg.getCanRemoveChessCount());
			break;
		case CONSTS.CMD_COVER:
			doc.setOnCover(msg.getFirstPos());//
			doc.setCurrentPlayer(msg.getCurrentPlayer());
			doc.setCurrentState(msg.getCurrentState());
			doc.setCanRemoveChessCount(msg.getCanRemoveChessCount());
			break;
		case CONSTS.CMD_MOVE:
			doc.setCurrentPlayer(msg.getCurrentPlayer());
			doc.setCurrentState(msg.getCurrentState());
			doc.setCanRemoveChessCount(msg.getCanRemoveChessCount());
			doc.move(msg.getFirstPos(), msg.getSecondPos());
			break;
		case CONSTS.CMD_CUT:
			doc.cutChess(msg.getFirstPos());
			doc.setCurrentPlayer(msg.getCurrentPlayer());
			doc.setCurrentState(msg.getCurrentState());
			doc.setCanRemoveChessCount(msg.getCanRemoveChessCount());
			break;
		default:
			break;
		}
	}

	public FivetigerJFrame getView() {
		return view;
	}

	public void setView(FivetigerJFrame view) {
		this.view = view;
	}

	public Document getDoc() {
		return doc;
	}

	public void setDoc(Document doc) {
		this.doc = doc;
	}

}
